// internal/apps/auth/controllers/auth_controller.go
package controllers

import (
	"star-go-app/internal/apps/auth/serializers"
	"star-go-app/internal/apps/auth/services"
	"star-go-app/pkg/common/utils/response"
	"strings"

	"github.com/gin-gonic/gin"
)

// AuthController 认证控制器
type AuthController struct {
	authService services.AuthService
}

// NewAuthController 创建认证控制器实例
func NewAuthController() *AuthController {
	return &AuthController{
		authService: services.NewAuthService(),
	}
}

// Login 用户登录
// @Summary 用户登录
// @Description 用户通过用户名和密码登录，返回访问令牌和刷新令牌。支持JSON和表单两种传参方式
// @Tags 认证
// @Accept json,x-www-form-urlencoded
// @Produce json
// @Param request body serializers.LoginRequest true "登录请求(JSON格式)"
// @Param username formData string false "用户名(表单格式)"
// @Param password formData string false "密码(表单格式)"
// @Success 200 {object} response.Response{data=serializers.TokenResponse} "登录成功"
// @Failure 400 {object} response.Response "请求参数错误"
// @Failure 401 {object} response.Response "用户名或密码错误"
// @Router /api/auth/login [post]
func (ctrl *AuthController) Login(c *gin.Context) {
	var req serializers.LoginRequest
	if err := c.ShouldBind(&req); err != nil {
		response.FailWithMessage(c, response.INVALID_PARAMS, "请求参数错误", err.Error())
		return
	}
	// if err := c.ShouldBindJSON(&req); err != nil {
	// 	response.FailWithMessage(c, response.INVALID_PARAMS, "请求参数错误", err.Error())
	// 	return
	// }

	// 获取客户端信息
	clientInfo := services.ClientInfo{
		IPAddress:  getClientIP(c),
		UserAgent:  c.GetHeader("User-Agent"),
		DeviceInfo: getDeviceInfo(c),
	}

	// 调用服务层进行登录
	tokenResp, err := ctrl.authService.Login(&req, clientInfo)
	if err != nil {
		response.FailWithMessage(c, response.UNAUTHORIZED, "登录失败", err.Error())
		return
	}

	response.SuccessWithMessage(c, "登录成功", tokenResp)
}

// RefreshToken 刷新访问令牌
// @Summary 刷新访问令牌
// @Description 使用刷新令牌获取新的访问令牌。支持JSON和表单两种传参方式
// @Tags 认证
// @Accept json,x-www-form-urlencoded
// @Produce json
// @Param request body serializers.RefreshTokenRequest true "刷新令牌请求(JSON格式)"
// @Param refresh_token formData string false "刷新令牌(表单格式)"
// @Success 200 {object} response.Response{data=serializers.TokenResponse} "刷新成功"
// @Failure 400 {object} response.Response "请求参数错误"
// @Failure 401 {object} response.Response "刷新令牌无效"
// @Router /api/auth/refresh [post]
func (ctrl *AuthController) RefreshToken(c *gin.Context) {
	var req serializers.RefreshTokenRequest
	if err := c.ShouldBind(&req); err != nil {
		response.FailWithMessage(c, response.INVALID_PARAMS, "请求参数错误", err.Error())
		return
	}

	// 获取客户端信息
	clientInfo := services.ClientInfo{
		IPAddress:  getClientIP(c),
		UserAgent:  c.GetHeader("User-Agent"),
		DeviceInfo: getDeviceInfo(c),
	}

	// 调用服务层刷新token
	tokenResp, err := ctrl.authService.RefreshToken(&req, clientInfo)
	if err != nil {
		response.FailWithMessage(c, response.UNAUTHORIZED, "刷新令牌失败", err.Error())
		return
	}

	response.SuccessWithMessage(c, "令牌刷新成功", tokenResp)
}

// VerifyToken 验证令牌并获取用户信息
// @Summary 验证令牌
// @Description 验证令牌的有效性并返回用户信息，支持访问令牌和刷新令牌。支持JSON和表单两种传参方式
// @Tags 认证
// @Accept json,x-www-form-urlencoded
// @Produce json
// @Param request body serializers.VerifyTokenRequest true "验证令牌请求(JSON格式)"
// @Param token formData string false "令牌(表单格式)"
// @Success 200 {object} response.Response{data=serializers.AuthUserInfoResponse} "验证成功"
// @Failure 400 {object} response.Response "请求参数错误"
// @Failure 401 {object} response.Response "令牌无效"
// @Router /api/auth/verify [post]
func (ctrl *AuthController) VerifyToken(c *gin.Context) {
	var req serializers.VerifyTokenRequest
	if err := c.ShouldBind(&req); err != nil {
		response.FailWithMessage(c, response.INVALID_PARAMS, "请求参数错误", err.Error())
		return
	}

	// 调用服务层验证token
	userInfo, err := ctrl.authService.VerifyToken(req.Token)
	if err != nil {
		response.FailWithMessage(c, response.UNAUTHORIZED, "令牌验证失败", err.Error())
		return
	}

	response.SuccessWithMessage(c, "令牌验证成功", userInfo)
}

// Logout 用户登出
// @Summary 用户登出
// @Description 用户登出，使当前访问令牌和刷新令牌失效。支持JSON和表单两种传参方式
// @Tags 认证
// @Accept json,x-www-form-urlencoded
// @Produce json
// @Param request body serializers.LogoutRequest true "登出请求(JSON格式)"
// @Param token formData string false "访问令牌(表单格式)"
// @Success 200 {object} response.Response "登出成功"
// @Failure 400 {object} response.Response "请求参数错误"
// @Failure 401 {object} response.Response "令牌无效"
// @Router /api/auth/logout [post]
func (ctrl *AuthController) Logout(c *gin.Context) {
	var req serializers.LogoutRequest
	if err := c.ShouldBind(&req); err != nil {
		response.FailWithMessage(c, response.INVALID_PARAMS, "请求参数错误", err.Error())
		return
	}

	// 调用服务层进行登出
	if err := ctrl.authService.Logout(req.Token); err != nil {
		response.FailWithMessage(c, response.ERROR, "登出失败", err.Error())
		return
	}

	response.SuccessWithMessage(c, "登出成功", nil)
}

// getClientIP 获取客户端IP地址
func getClientIP(c *gin.Context) string {
	// 优先从X-Forwarded-For头获取
	if ip := c.GetHeader("X-Forwarded-For"); ip != "" {
		return strings.Split(ip, ",")[0]
	}
	// 其次从X-Real-IP头获取
	if ip := c.GetHeader("X-Real-IP"); ip != "" {
		return ip
	}
	// 最后从RemoteAddr获取
	return c.ClientIP()
}

// getDeviceInfo 获取设备信息（简单实现）
func getDeviceInfo(c *gin.Context) string {
	userAgent := c.GetHeader("User-Agent")
	if userAgent == "" {
		return "Unknown Device"
	}

	// 简单的设备识别逻辑
	switch {
	case strings.Contains(userAgent, "Mobile"):
		return "Mobile Device"
	case strings.Contains(userAgent, "Tablet"):
		return "Tablet Device"
	case strings.Contains(userAgent, "Desktop"):
		return "Desktop Device"
	default:
		return "Unknown Device"
	}

}
